package puzzle.game.states;

import org.newdawn.slick.Color;
import org.newdawn.slick.Font;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.Music;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Sound;
import org.newdawn.slick.particles.ConfigurableEmitter;
import org.newdawn.slick.state.StateBasedGame;
import org.newdawn.slick.util.Log;

import cyber2d.core.PlatformerLevel;
import cyber2d.core.objects.Creature;
import puzzle.core.Direction;
import puzzle.core.GameContext;
import puzzle.core.LevelMap;
import puzzle.core.Player;
import puzzle.game.BallPuzzle;
import puzzle.game.MapList;
import puzzle.game.states.LoadingState;
import puzzle.game.states.PuzzleState;
import puzzle.game.ui.PuzzleButton;
import puzzle.util.ResourceManager;

public abstract class IngameState extends PuzzleState implements GameContext {
  
  public IngameState(BallPuzzle ctx) {
    super(ctx);
  }
  
  
  
  //cyber2d
  PlatformerLevel level;
  boolean paused;
  //Creature player;
  //bpuz
  //protected LevelMap level;
  //Player player;
  
  protected MapList maps;
  
  protected int currentMap = 0;
  
  protected String levelStr = ResourceManager.getString("game.msg.level", "Level");
  protected String escStr = ResourceManager.getString("game.msg.to_main","Press R for restart");
  protected String titleStr = ResourceManager.getString("name","cyber2d");
  
  public static final int CONTROLS_UP = Input.KEY_UP;
  public static final int CONTROLS_DOWN = Input.KEY_DOWN;
  public static final int CONTROLS_LEFT = Input.KEY_LEFT;
  public static final int CONTROLS_RIGHT = Input.KEY_RIGHT;
  
  protected int helpx = 0;
  protected int helpy = 0;
  
  public void initState(GameContainer container) throws SlickException {
    setBackground(new Color(87, 146, 186));
  }
  
  public void enter(GameContainer container, StateBasedGame game) throws SlickException {
    super.enter(container, game);
    Music beat = getContext().getMusic();
    if (beat!=null) {
        beat.loop();
    }
  }
  
  public void leave(GameContainer container, StateBasedGame game) throws SlickException {
    super.leave(container, game);
    Music beat = getContext().getMusic();
    if (beat!=null) {
        beat.pause();
    }
  }
  
  public void startState(GameContainer container) throws SlickException {
    if (!getContext().getLoadingState().isDone()) 
      Log.warn("Starting IngameState before loading is finished.");
    
    maps = getStateMapList();
    
    level = new PlatformerLevel();
    
    if (currentMap<0||currentMap>maps.size()-1)
      currentMap=0;
    
    //start off with current map
    //level.setData(maps.getData(currentMap));
    
    //gets preloaded image
    //Image ballImg = getContext().getLoadingState().getBallImage();
    
    //workaround to a bug in an older version of Slick
    ConfigurableEmitter.setRelativePath("data");
    //create player
    //String srf = ResourceManager.getString("particle.port", "data/particles/small-explosion.xml");
    //player = new Player(ballImg, srf, this);
  }
  
  public void renderState(GameContainer container, Graphics g) {
    if (level==null) {
      return;
    }
    
    //old values
    Color old = g.getColor();
    Font font = g.getFont();
    
    //center x/y for the map
    float cx = container.getWidth()/2.0f - LevelMap.PIXEL_WIDTH/2.0f;
    float cy = (container.getHeight()/2.0f - LevelMap.PIXEL_HEIGHT/2.0f)-10;
    
    //////////////////////
    /// GRAPHICS SETUP ///
    
    //Since the map and player are all drawn to 0, 0, the Graphics context
    //must be translated to center the map.
    
    g.translate((int)cx, (int)cy);
    
    //////////////////////
    /// GAME RENDERING ///
    
    //set clip so we don't draw the ball outside of the map
    g.setClip((int)cx, (int)cy-1, LevelMap.PIXEL_WIDTH+1, LevelMap.PIXEL_HEIGHT+1);
    
    //render the map tiles 
    level.render(g);
    
    //render the ball
    //player.render(g);
    
    //renders level border
    g.setColor(LevelMap.GRID_COLOR);
    g.drawRect(0, 0, LevelMap.PIXEL_WIDTH, LevelMap.PIXEL_HEIGHT);
    
    //reset transformation & clipping
    g.clearClip();
    g.translate((int)-cx, (int)-cy);
    
    ///////////////////////
    /// TITLE RENDERING ///
    
    //TITLE colour
    g.setColor(Color.white);
    
    //BPuz title
    /*float ctx = container.getWidth()/2.0f - font.getWidth(titleStr)/2.0f;
    float cty = cy - font.getHeight(titleStr) - 5;
    g.drawString(titleStr, (int)ctx, (int)cty);*/
    
    //////////////////////
    /// TEXT RENDERING ///
    
    //FOREGROUND colour
    g.setColor(Color.white);
    
    //current map index
    //String msg = levelStr+": "+(currentMap+1)+" / "+maps.size();
    int ltx = (int)cx + 5;
    int lty = (int)cy + LevelMap.PIXEL_HEIGHT+3;
    //g.drawString(msg, ltx, lty);
    
    /*//map name & author
    lty += (font.getHeight(msg)+3);
    msg = getMapText(maps.get(currentMap));
    if (msg!=null&&msg.length()!=0)
      g.drawString(msg, ltx, lty);*/
    
    //help text
    ltx = (int)cx + LevelMap.PIXEL_WIDTH-5-font.getWidth(escStr);
    lty = (int)cy + LevelMap.PIXEL_HEIGHT+3;
    helpx = ltx;
    helpy = lty;
    g.drawString(escStr, ltx, lty);
    
    //render sound button
    try
	{
		getContext().getSoundSwitch().render(container, g);
	} catch (SlickException e)
	{
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
    
    //////////////////////
    /// RESET GRAPHICS ///
    
    //reset old info
    g.setFont(font);
    g.setColor(old);
  }
  
  public void updateState(GameContainer container, int delta) {
    if (level==null)
      return;
    
    //if not paused - update
    if(!paused)
    {
    	level.update();
    }
    
    Input in = container.getInput();
    
    /*//check to see whether we can move the player    
    if (!player.isMoving()) {
      if (in.isKeyDown(CONTROLS_UP)) {
        player.setDirection(Direction.UP);
      }       
      else if (in.isKeyDown(CONTROLS_DOWN)) {
        player.setDirection(Direction.DOWN);
      }
      else if (in.isKeyDown(CONTROLS_LEFT)) {
        player.setDirection(Direction.LEFT);
      }
      else if (in.isKeyDown(CONTROLS_RIGHT)) {
        player.setDirection(Direction.RIGHT);
      }
    }*/
    
    //updates the player's position
    //player.update(container, delta);
  }
  
  //when key pressed
  public void keyPressed(int key, char c)
  {
    super.keyPressed(key, c);
    if (key == Input.KEY_R)
    {
    	level = new PlatformerLevel();
    }
    else if(key == Input.KEY_W)
    {
    	level.player.wantJump(true);
    }
    else if(key == Input.KEY_A)
    {
    	level.player.wantDirection(-1);
    }
    else if(key == Input.KEY_D)
    {
    	level.player.wantDirection(1);
    }
    else if(key == Input.KEY_P)
    {
    	paused = !paused;
    }
    else if(key == Input.KEY_SPACE)
    {
    	level.player.wantShoot(true);
    }
    else if (key == Input.KEY_ESCAPE)
    {

    }
  }
  
  //whan key released
  public void keyReleased(int key, char c)
  {
	  super.keyPressed(key, c);
	  if(key == Input.KEY_W)
	  {
		  level.player.wantJump(false);
	  }
	  else if(key == Input.KEY_A)
	  {
		  level.player.wantDirection(1);
	  }
	  else if(key == Input.KEY_D)
	  {
		  level.player.wantDirection(-1);
	  }
	  else if(key == Input.KEY_SPACE)
	    {
	    	level.player.wantShoot(false);
	    }
	  else if (key == Input.KEY_ESCAPE)
	  {

	  }	  
  }
  
  /**
   * With user map info, the map name and author should be given.
   * Since the author for the game maps tend to be the developer,
   * there is no point in drawing the author on the standard game state.
   */
  public abstract String getMapText(MapList.Entry e);
  
  /**
   * Ends the current level and starts up the next one.
   */
  public abstract void endLevel();
  
  /** 
   * Gets the MapList for this IngameState.
   */
  protected abstract MapList getStateMapList();
  
  public Sound getPortSound() {
    return getContext().getLoadingState().getPortSound();
  }
  
  public Sound getEndSound() {
    return getContext().getLoadingState().getEndSound();
  }
  
  
  public int getMapIndex() {
    return currentMap;
  }
  
  public LevelMap getCurrentLevel()
  {
  	// TODO Auto-generated method stub
  	return null;
  }

  
}